<template>
  <editor
    api-key="d6xtm5va0cagta3av9l5ppdrzmfwxjio5vbzjrresmifmlzv"
    :init="mergeInit"
    v-bind="$attrs"
    :id="id"
  />
</template>

<script setup lang="ts">
/**
 * 如在naiveui等ui组件弹窗中使用,应设置让焦点不锁定在modal内部, 如naiveui的弹窗设置trap-focus=false
 */
import { v4 as uuidv4 } from 'uuid'
import Editor from '@tinymce/tinymce-vue'

const props = withDefaults(
  defineProps<{
    size?: number
    init?: object // 初始化参数
    accept?: string // 多媒体上传文件类型
  }>(),
  {
    size: 10
  }
)

const id = uuidv4() // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
console.log(id)

const mergeInit = computed(() => {
  return {
    height: 500,
    menubar: true,
    language: 'zh_CN',
    images_upload_handler,
    file_picker_callback,
    branding: false,
    plugins: [
      'a11ychecker',
      'advlist',
      'advcode',
      'advtable',
      'autolink',
      'checklist',
      'export',
      'lists',
      'link',
      'image',
      'charmap',
      'preview',
      'anchor',
      'searchreplace',
      'visualblocks',
      'powerpaste',
      'fullscreen',
      'formatpainter',
      'insertdatetime',
      'media',
      'table',
      'help',
      'wordcount'
    ],
    toolbar:
      'undo redo | casechange blocks | bold italic backcolor | \
           alignleft aligncenter alignright alignjustify | \
           bullist numlst checklist outdent indent | removeformat | a11ycheck code table help | image | media',
    ...props.init
  }
})

// 基本上传oss方法
function uploadHandle(file: any, name: string, resolve: any, reject?: any) {
  const xhr = new XMLHttpRequest()
  xhr.withCredentials = false
  xhr.open('GET', 'https://common-service-api.hsmap.com/?bucket=isp-prod')
  xhr.setRequestHeader('token', 'fsd2!##@dsadas')

  xhr.onload = () => {
    if (xhr.status === 403) {
      reject({ message: 'HTTP Error: ' + xhr.status, remove: true })
      return
    }

    if (xhr.status < 200 || xhr.status >= 300) {
      reject('HTTP Error: ' + xhr.status)
      return
    }

    const json = JSON.parse(xhr.response).result
    console.log(xhr, json)

    if (!json) {
      reject('Invalid JSON: ' + xhr.responseText)
      return
    }

    const formData = new FormData()
    let flieUrl = ''
    flieUrl = json.host
    formData.append('key', `${json.dir}/${name}`)
    formData.append('policy', json.policy)
    formData.append('OSSAccessKeyId', json.accessKeyId)
    formData.append('success_action_status', '200')
    formData.append('signature', json.signature)
    formData.append('file', file, name)
    const request = new XMLHttpRequest()

    request.upload.onprogress = (e) => {
      console.log(e)
      // progress((e.loaded / e.total) * 100)
    }

    request.open('POST', flieUrl)
    request.setRequestHeader('token', 'fsd2!##@dsadas')
    request.send(formData)

    request.onload = function (e) {
      console.log(e)
      resolve(flieUrl + `/${json.dir}/` + `${name}`)
    }
  }

  xhr.onerror = () => {
    reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status)
  }
  xhr.send()
}

// 插入图片上传模块触发, 需在init参数中设置images_upload_handler
function images_upload_handler(blobInfo: any, progress: Function) {
  return new Promise((resolve, reject) => {
    console.log(blobInfo, '-----', progress)

    const file = blobInfo.blob()
    const name = blobInfo.filename()
    console.log(file)

    const { size } = file

    // 该方法tinymce已做处理,不属于图片类型的文件将不会触发此方法,只需限制图片大小即可

    // 转换单位, 检查文件大小
    const limitSize = props.size * 1024 * 1024
    if (size > limitSize) {
      window.$message.warning(`上传文件不能大于${props.size}M`)
      reject(`上传文件不能大于${props.size}M`)
    }

    uploadHandle(file, name, resolve, reject)
  })
}

// 文件上传触发, 需在init参数中设置file_picker_callback
function file_picker_callback(callback: any, value: any, meta: any) {
  const { filetype } = meta

  // 创建文件选择
  const inputElem = document.createElement('input')
  inputElem.setAttribute('type', 'file')

  // 限制上传文件类型
  let limitFileType = ''
  let defaultFiletype = ''
  switch (filetype) {
    case 'image':
      defaultFiletype = '.jpg,.jpeg,.png,.gif'
      break
    case 'media':
      defaultFiletype = '.mp3,.mp4,.mkv,.avi,.wmv,.rmvb,.mov,.mpg,.mpeg,.webm'
      break
    default:
      break
  }
  limitFileType = props.accept ?? defaultFiletype
  inputElem.setAttribute('accept', limitFileType)

  inputElem.onchange = () => {
    const file = (inputElem.files as FileList)[0] //获取文件信息

    const { size, name } = file

    // 判断文件类型
    const suffix = name.substring(name.lastIndexOf('.')).toLowerCase()
    const isMatch = limitFileType.split(',').includes(suffix)
    if (!isMatch) {
      window.$message.warning(`请上传${limitFileType}类型的文件`)
      return
    }

    // 转换单位
    const limitSize = props.size * 1024 * 1024
    if (size > limitSize) {
      window.$message.warning(`上传文件不能大于${props.size}M`)
      return
    }

    // oss上传
    uploadHandle(file, name, callback)
  }

  inputElem.click()
}
</script>

<style lang="less" scoped></style>
